// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraCharacterMovementComponent.h"

#include "AbilitySystemComponent.h"
#include "AbilitySystemGlobals.h"
#include "Components/CapsuleComponent.h"
#include "Engine/World.h"
#include "GameFramework/Character.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraCharacterMovementComponent)

UE_DEFINE_GAMEPLAY_TAG(TAG_Gameplay_MovementStopped, "Gameplay.MovementStopped"); // 定义游戏标签：移动停止

namespace LyraCharacter
{
	static float GroundTraceDistance = 100000.0f; // 地面追踪距离
	FAutoConsoleVariableRef CVar_GroundTraceDistance(TEXT("LyraCharacter.GroundTraceDistance"), GroundTraceDistance, TEXT("Distance to trace down when generating ground information."), ECVF_Cheat); // 自动控制台变量引用：地面追踪距离
};

/**
 * 构造函数
 */
ULyraCharacterMovementComponent::ULyraCharacterMovementComponent(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer) // 调用父类构造函数
{
}

/**
 * 模拟移动
 */
void ULyraCharacterMovementComponent::SimulateMovement(float DeltaTime)
{
	if (bHasReplicatedAcceleration) // 如果有复制加速度
	{
		// 保留我们的复制加速度
		const FVector OriginalAcceleration = Acceleration; // 原始加速度
		Super::SimulateMovement(DeltaTime); // 调用父类模拟移动
		Acceleration = OriginalAcceleration; // 恢复加速度
	}
	else // 否则
	{
		Super::SimulateMovement(DeltaTime); // 调用父类模拟移动
	}
}

/**
 * 检查是否可以尝试跳跃
 */
bool ULyraCharacterMovementComponent::CanAttemptJump() const
{
	// 与UCharacterMovementComponent的实现相同，但没有下蹲检查
	return IsJumpAllowed() && // 跳跃是否允许
		(IsMovingOnGround() || IsFalling()); // 包括下落状态用于双跳和非零跳跃保持时间，但由角色验证
}

/**
 * 初始化组件
 */
void ULyraCharacterMovementComponent::InitializeComponent()
{
	Super::InitializeComponent(); // 调用父类方法
}

/**
 * 获取地面信息
 */
const FLyraCharacterGroundInfo& ULyraCharacterMovementComponent::GetGroundInfo()
{
	if (!CharacterOwner || (GFrameCounter == CachedGroundInfo.LastUpdateFrame)) // 如果角色所有者不存在或帧计数器等于缓存地面信息最后更新帧
	{
		return CachedGroundInfo; // 返回缓存地面信息
	}

	if (MovementMode == MOVE_Walking) // 如果移动模式是行走
	{
		CachedGroundInfo.GroundHitResult = CurrentFloor.HitResult; // 缓存地面碰撞结果
		CachedGroundInfo.GroundDistance = 0.0f; // 缓存地面距离
	}
	else // 否则
	{
		const UCapsuleComponent* CapsuleComp = CharacterOwner->GetCapsuleComponent(); // 获取胶囊体组件
		check(CapsuleComp); // 检查胶囊体组件

		const float CapsuleHalfHeight = CapsuleComp->GetUnscaledCapsuleHalfHeight(); // 胶囊体半高
		const ECollisionChannel CollisionChannel = (UpdatedComponent ? UpdatedComponent->GetCollisionObjectType() : ECC_Pawn); // 碰撞通道
		const FVector TraceStart(GetActorLocation()); // 追踪起点
		const FVector TraceEnd(TraceStart.X, TraceStart.Y, (TraceStart.Z - LyraCharacter::GroundTraceDistance - CapsuleHalfHeight)); // 追踪终点

		FCollisionQueryParams QueryParams(SCENE_QUERY_STAT(LyraCharacterMovementComponent_GetGroundInfo), false, CharacterOwner); // 碰撞查询参数
		FCollisionResponseParams ResponseParam; // 碰撞响应参数
		InitCollisionParams(QueryParams, ResponseParam); // 初始化碰撞参数

		FHitResult HitResult; // 碰撞结果
		GetWorld()->LineTraceSingleByChannel(HitResult, TraceStart, TraceEnd, CollisionChannel, QueryParams, ResponseParam); // 单线追踪

		CachedGroundInfo.GroundHitResult = HitResult; // 缓存地面碰撞结果
		CachedGroundInfo.GroundDistance = LyraCharacter::GroundTraceDistance; // 缓存地面距离

		if (MovementMode == MOVE_NavWalking) // 如果移动模式是导航行走
		{
			CachedGroundInfo.GroundDistance = 0.0f; // 缓存地面距离为0
		}
		else if (HitResult.bBlockingHit) // 如果有阻挡碰撞
		{
			CachedGroundInfo.GroundDistance = FMath::Max((HitResult.Distance - CapsuleHalfHeight), 0.0f); // 缓存地面距离
		}
	}

	CachedGroundInfo.LastUpdateFrame = GFrameCounter; // 缓存最后更新帧

	return CachedGroundInfo; // 返回缓存地面信息
}

/**
 * 设置复制加速度
 */
void ULyraCharacterMovementComponent::SetReplicatedAcceleration(const FVector& InAcceleration)
{
	bHasReplicatedAcceleration = true; // 设置是否有复制加速度为true
	Acceleration = InAcceleration; // 设置加速度
}

/**
 * 获取增量旋转
 */
FRotator ULyraCharacterMovementComponent::GetDeltaRotation(float DeltaTime) const
{
	if (UAbilitySystemComponent* ASC = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetOwner())) // 获取能力系统组件
	{
		if (ASC->HasMatchingGameplayTag(TAG_Gameplay_MovementStopped)) // 如果匹配移动停止游戏标签
		{
			return FRotator(0,0,0); // 返回零旋转
		}
	}

	return Super::GetDeltaRotation(DeltaTime); // 调用父类方法
}

/**
 * 获取最大速度
 */
float ULyraCharacterMovementComponent::GetMaxSpeed() const
{
	if (UAbilitySystemComponent* ASC = UAbilitySystemGlobals::GetAbilitySystemComponentFromActor(GetOwner())) // 获取能力系统组件
	{
		if (ASC->HasMatchingGameplayTag(TAG_Gameplay_MovementStopped)) // 如果匹配移动停止游戏标签
		{
			return 0; // 返回0
		}
	}

	return Super::GetMaxSpeed(); // 调用父类方法
}